﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Text;
using SharpCommunications.Cryptography;
using SharpCommunications.Interfaces;
using SharpCommunications.Logging;
using Location = SharpCommunications.Logging.Location;

using ARD.Common;

namespace SharpCommunications.Connection
{
    public class SharpChannelClient : IDisposable
    {
        protected string machineName;
        protected int port;
        protected ISharpConnectionEndpoint endpoint;
        protected TcpClient tcpClient;
        protected bool disposing = false;

        //protected ThreadPool<>

        public event ReceivedMessageHandlerDelegate OnReceive;

        public SharpChannelClient(string machineName, int port, string keyFilePath = null)
        {
            Location location = new Location("SharpCommunications.Connection.SharpClient.SharpClient()");

            this.machineName = machineName;
            this.port = port;

            ISharpCryptographer cryptographer = null;

            if (keyFilePath != null)
            {
                cryptographer = new DefaultCryptographer(keyFilePath);
            }

            this.endpoint = new SharpConnectionEndpoint(cryptographer);

    	    tcpClient = new TcpClient(machineName, port);
            LogFactory.Log.DebugMessage(location, "Connected");
            this.endpoint.Initialize(tcpClient);

            this.endpoint.ReceivedMessage += new ReceivedMessageHandlerDelegate(endpoint_ReceivedMessage);
            this.endpoint.Disconnected += new DisconnectedHandlerDelegate(endpoint_Disconnected);

        }

        #region IDisposable Members

        public void Dispose()
        {
            this.disposing = true;
            NetworkStream stream = tcpClient.GetStream();
            stream.Close();
        }

        #endregion



        public void SendMessage(string message)
        {
            this.endpoint.SendMessage(message);
        }

        

        protected void endpoint_Disconnected(ISharpConnectionEndpoint connectionEndpoint)
        {
            Location location = new Location("SharpCommunications.Connection.SharpClient.endpoint_Disconnected()");
            LogFactory.Log.DebugMessage(location, "Disconnected");

            if (!this.disposing)
            {
                try
                {
                    tcpClient = new TcpClient(machineName, port);
                    LogFactory.Log.DebugMessage(location, "Connected");
                    connectionEndpoint.Initialize(tcpClient);
                }
                catch (Exception ex)
                {
                    LogFactory.Log.ErrorMessage(location, ex, true);
                }
            }
        }

        protected void endpoint_ReceivedMessage(ISharpConnectionEndpoint connectionEndpoint, string message)
        {
            Location location = new Location("SharpCommunications.Connection.SharpClient.endpoint_ReceivedMessage()");

            if(this.OnReceive != null)
            {
                this.OnReceive(connectionEndpoint, message);
            }
        }
    }
}
